//---------------------------------------------------------------------------------
// Copyright (c) 2008 VoiceLynx Project
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//     1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//
//     2. Altered source versions must be plainly marked as such, and must not be
//        misrepresented as being the original software.
//
//     3. This notice may not be removed or altered from any source
//        distribution.
//---------------------------------------------------------------------------------

#include "VLPrerequisites.h"

#include "wx/config.h"

#include "VLUserSettings.h"

#include "VLClientApp.h"

// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
//BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    //EVT_MENU(Minimal_Quit,  MyFrame::OnQuit)
    //EVT_MENU(Minimal_About, MyFrame::OnAbout)
//END_EVENT_TABLE()

// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also implements the accessor function
// wxGetApp() which will return the reference of the right type (i.e. VLClientApp and
// not wxApp)
IMPLEMENT_APP(VLClientApp)


VLCoreLoopThread::VLCoreLoopThread(VLClientApp &app)
: wxThread(wxTHREAD_JOINABLE),
  mApp(app)
{

}

void VLCoreLoopThread::start()
{
  Create();
  Run();
}

void VLCoreLoopThread::stop()
{
  Delete();
}

void *VLCoreLoopThread::Entry()
{
  while (true)
  {
    mApp.loop();

    if (TestDestroy())
    {
      break;
    }

    //wxThread::Yield();
    wxThread::Sleep(1);
  }

  return 0;
}

VLClientApp::VLClientApp()
: mCoreThread(*this)
{
  
}

// 'Main program' equivalent: the program execution "starts" here
bool VLClientApp::OnInit()
{
  VL_INIT_DEBUG_CONSOLE();

  // call the base class initialization method, currently it only parses a
  // few common command-line options but it could be do more in the future
  if ( !wxApp::OnInit() )
      return false;

  // create the main application window
  mMainFrame = new UI_MainFrameExt(NULL);

  // create the hid manager (which initializes OIS using the current window handle)
  mHidManager.initialize(mMainFrame);
  
  // and show it (the frames, unlike simple controls, are not shown when
  // created initially)
  mMainFrame->Show(true);

  // Do some application-specific initializationg
  mMainFrame->Init();

  // Create the core
  mClient.getCore().setController(&mPushToTalkController);

  wxThread::Sleep(500);

  //mCore->connect(VLString("localhost"), 17899);

  // Begin servicing the core app in a seperate thread
  mCoreThread.start();

  // success: wxApp::OnRun() will be called which will enter the main message
  // loop and the application will run. If we returned false here, the
  // application would exit immediately.
  return true;
}

int VLClientApp::OnExit()
{
  // Stop servicing the core
  mCoreThread.stop();

  return wxApp::OnExit();
}

UI_MainFrameExt * VLClientApp::getMainFrame()
{
  return mMainFrame;
}

void VLClientApp::loop()
{
  VL_BEGIN_CORE_CRITICAL_SECTION();

  mHidManager.capture();
  mPushToTalkController.update(mHidManager);

  mClient.process();

  VL_END_CORE_CRITICAL_SECTION();
}
